//
//  DateExtension.swift
//  DemoNavBar
//
//  Created by YangHuan on 2019/12/13.
//  Copyright © 2019 YangHuan. All rights reserved.
//

import Foundation


 extension Date {
    
    public func plus(seconds s: UInt) -> Date {
        return self.addComponentsToDate(seconds: Int(s), minutes: 0, hours: 0, days: 0, weeks: 0, months: 0, years: 0)
    }
    
    public func minus(seconds s: UInt) -> Date {
        return self.addComponentsToDate(seconds: -Int(s), minutes: 0, hours: 0, days: 0, weeks: 0, months: 0, years: 0)
    }
    
    public func plus(minutes m: UInt) -> Date {
        return self.addComponentsToDate(seconds: 0, minutes: Int(m), hours: 0, days: 0, weeks: 0, months: 0, years: 0)
    }
    
    public func minus(minutes m: UInt) -> Date {
        return self.addComponentsToDate(seconds: 0, minutes: -Int(m), hours: 0, days: 0, weeks: 0, months: 0, years: 0)
    }
    
    public func plus(hours h: UInt) -> Date {
        return self.addComponentsToDate(seconds: 0, minutes: 0, hours: Int(h), days: 0, weeks: 0, months: 0, years: 0)
    }
    
    public func minus(hours h: UInt) -> Date {
        return self.addComponentsToDate(seconds: 0, minutes: 0, hours: -Int(h), days: 0, weeks: 0, months: 0, years: 0)
    }
    
    public func plus(days d: UInt) -> Date {
        return self.addComponentsToDate(seconds: 0, minutes: 0, hours: 0, days: Int(d), weeks: 0, months: 0, years: 0)
    }
    
    public func minus(days d: UInt) -> Date {
        return self.addComponentsToDate(seconds: 0, minutes: 0, hours: 0, days: -Int(d), weeks: 0, months: 0, years: 0)
    }
    
    public func plus(weeks w: UInt) -> Date {
        return self.addComponentsToDate(seconds: 0, minutes: 0, hours: 0, days: 0, weeks: Int(w), months: 0, years: 0)
    }
    
    public func minus(weeks w: UInt) -> Date {
        return self.addComponentsToDate(seconds: 0, minutes: 0, hours: 0, days: 0, weeks: -Int(w), months: 0, years: 0)
    }
    
    public func plus(months m: UInt) -> Date {
        return self.addComponentsToDate(seconds: 0, minutes: 0, hours: 0, days: 0, weeks: 0, months: Int(m), years: 0)
    }
    
    public func minus(months m: UInt) -> Date {
        return self.addComponentsToDate(seconds: 0, minutes: 0, hours: 0, days: 0, weeks: 0, months: -Int(m), years: 0)
    }
    
    public func plus(years y: UInt) -> Date {
        return self.addComponentsToDate(seconds: 0, minutes: 0, hours: 0, days: 0, weeks: 0, months: 0, years: Int(y))
    }
    
    public func minus(years y: UInt) -> Date {
        return self.addComponentsToDate(seconds: 0, minutes: 0, hours: 0, days: 0, weeks: 0, months: 0, years: -Int(y))
    }
    
    fileprivate func addComponentsToDate(seconds sec: Int, minutes min: Int, hours hrs: Int, days d: Int, weeks wks: Int, months mts: Int, years yrs: Int) -> Date {
        var dc = DateComponents()
        dc.second = sec
        dc.minute = min
        dc.hour = hrs
        dc.day = d
        dc.weekOfYear = wks
        dc.month = mts
        dc.year = yrs
        return Calendar.current.date(byAdding: dc, to: self)!
    }
    
    public func midnightUTCDate() -> Date {
        var dc: DateComponents = Calendar.current.dateComponents([.year, .month, .day], from: self)
        dc.hour = 0
        dc.minute = 0
        dc.second = 0
        dc.nanosecond = 0
        dc.timeZone = TimeZone(secondsFromGMT: 0)
        return Calendar.current.date(from: dc)!
    }
    
    public static func secondsBetween(date1 d1:Date, date2 d2:Date) -> Int {
        let dc = Calendar.current.dateComponents([.second], from: d1, to: d2)
        return dc.second!
    }
    
    public static func minutesBetween(date1 d1: Date, date2 d2: Date) -> Int {
        let dc = Calendar.current.dateComponents([.minute], from: d1, to: d2)
        return dc.minute!
    }
    
    public static func hoursBetween(date1 d1: Date, date2 d2: Date) -> Int {
        let dc = Calendar.current.dateComponents([.hour], from: d1, to: d2)
        return dc.hour!
    }
    
    public static func daysBetween(date1 d1: Date, date2 d2: Date) -> Int {
        let dc = Calendar.current.dateComponents([.day], from: d1, to: d2)
        return dc.day!
    }
    
    public static func weeksBetween(date1 d1: Date, date2 d2: Date) -> Int {
        let dc = Calendar.current.dateComponents([.weekOfYear], from: d1, to: d2)
        return dc.weekOfYear!
    }
    
    public static func monthsBetween(date1 d1: Date, date2 d2: Date) -> Int {
        let dc = Calendar.current.dateComponents([.month], from: d1, to: d2)
        return dc.month!
    }
    
    public static func yearsBetween(date1 d1: Date, date2 d2: Date) -> Int {
        let dc = Calendar.current.dateComponents([.year], from: d1, to: d2)
        return dc.year!
    }
    
    //MARK- Comparison Methods
    
    public func isGreaterThan(_ date: Date) -> Bool {
        return (self.compare(date) == .orderedDescending)
    }
    
    public func isLessThan(_ date: Date) -> Bool {
        return (self.compare(date) == .orderedAscending)
    }
    
    //MARK- Computed Properties
    
    public var day: UInt {
        return UInt(Calendar.current.component(.day, from: self))
    }
    
    public var month: UInt {
        return UInt(NSCalendar.current.component(.month, from: self))
    }
    
    public var year: UInt {
        return UInt(NSCalendar.current.component(.year, from: self))
    }
    
    public var hour: UInt {
        return UInt(NSCalendar.current.component(.hour, from: self))
    }
    
    public var minute: UInt {
        return UInt(NSCalendar.current.component(.minute, from: self))
    }
    
    public var second: UInt {
        return UInt(NSCalendar.current.component(.second, from: self))
    }
    
    // to YYYY-MM-DD-hh-mm-ss
    public var parseDate: String {
        return "\(year)-\(month)-\(day) \(hour):\(minute):\(second)"
    }
}


let kMinuteTimeInterval: TimeInterval = 60
let kHourTimeInterval: TimeInterval = 60 * kMinuteTimeInterval
let kDayTimeInterval: TimeInterval = 24 * kHourTimeInterval
let kWeekTimeInterval: TimeInterval = 7 * kDayTimeInterval
let kMonthTimeInterval: TimeInterval = 30 * kDayTimeInterval
let kYearTimeInterval: TimeInterval = 12 * kMonthTimeInterval

public extension Date {
    var isToday: Bool {
        let cal = Calendar.current
        var components = cal.dateComponents([Calendar.Component.era, Calendar.Component.year, Calendar.Component.month, Calendar.Component.day], from: Date())
        let today = cal.date(from: components)
        components = cal.dateComponents([Calendar.Component.era, Calendar.Component.year, Calendar.Component.month, Calendar.Component.day], from: self)
        let otherDay = cal.date(from: components)
        guard let day = today,
            let other = otherDay else { return false }
        return day == other
    }
    
    var isYesterday: Bool {
        let cal = Calendar.current
        var components = cal.dateComponents([Calendar.Component.era, Calendar.Component.year, Calendar.Component.month, Calendar.Component.day], from: Date())
        let today = cal.date(from: components)
        let yesterday = today?.addingTimeInterval(-kDayTimeInterval)
        components = cal.dateComponents([Calendar.Component.era, Calendar.Component.year, Calendar.Component.month, Calendar.Component.day], from: self)
        let otherDay = cal.date(from: components)
        guard let day = yesterday,
            let other = otherDay else { return false }
        return day == other
    }
}

public extension Date {
    static func ptimeAgoSinceDate(_ date: Date, numericDates: Bool) -> String {
        let calendar = Calendar.current
        let now = Date()
        let earliest = (now as NSDate).earlierDate(date)
        let latest = (earliest == now) ? date : now
        let components:DateComponents = (calendar as NSCalendar).components([
            NSCalendar.Unit.minute,
            NSCalendar.Unit.hour,
            NSCalendar.Unit.day,
            NSCalendar.Unit.weekOfYear,
            NSCalendar.Unit.month,
            NSCalendar.Unit.year,
            NSCalendar.Unit.second
            ], from: earliest, to: latest, options: NSCalendar.Options())
        
        if (components.year! >= 2) {
            return ""
            //            return "\(String(describing: components.year)) 年前"
        } else if (components.year! >= 1){
            return ""
            //            if (numericDates){
            //                return "1 年前"
            //            } else {
            //                return "去年"
            //            }
        } else if (components.month! >= 2) {
            return ""
            //            return "\(String(describing: components.month)) 月前"
        } else if (components.month! >= 1){
            return ""
            //            if (numericDates){
            //                return "1 个月前"
            //            } else {
            //                return "上个月"
            //            }
        } else if (components.weekOfYear! >= 2) {
            return ""
            //            return "\(String(describing: components.weekOfYear)) 周前"
        } else if (components.weekOfYear! >= 1){
            return ""
            //            if (numericDates){
            //                return "1 周前"
            //            } else {
            //                return "上一周"
            //            }
        } else if (components.day! >= 2) {
            return ""
            //            return "\(String(describing: components.day)) 天前"
        } else if (components.day! >= 1){
            //            if (numericDates){
            //                return "1 天前"
            //            } else {
            //                return "昨天"
            //            }
            return ""
        } else if (components.hour! >= 2) {
            return "\(components.hour!) 小时前"
        } else if (components.hour! >= 1){
            return "1 小时前"
        } else if (components.minute! >= 2) {
            return "\(components.minute!) 分钟前"
        } else if (components.minute! >= 1){
            return "1 分钟前"
        } else if (components.second! >= 3) {
            return "\(components.second!) 秒前"
        } else {
            return "刚刚"
        }
    }
}


public extension TimeInterval {
    
    var date: Date {
        return Date(timeIntervalSince1970: self)
    }
    
    func chatConversitionTime(timeAgo: Bool = false) -> String {
        if timeAgo {
            let str = Date.ptimeAgoSinceDate(date, numericDates: true)
            if !str.isEmpty {
                return str
            }
        }
        if date.isToday {
            let df = DateFormatter()
            df.dateFormat = "aHH:mm"
            df.amSymbol = "上午"
            df.pmSymbol = "下午"
            return df.string(from: date)
        }
        if date.isYesterday {
            let df = DateFormatter()
            df.dateFormat = "aHH:mm"
            df.amSymbol = "昨天"
            df.pmSymbol = "昨天"
            return df.string(from: date)
        }
        //        if self < kWeekTimeInterval {
        //            // 最近一周
        //            let df = DateFormatter()
        //            df.locale = Locale(identifier: "zh_CN")
        //            df.dateFormat = "ccc"
        //            return df.string(from: date)
        //        }
        
        let components = Calendar.current.dateComponents([Calendar.Component.era, Calendar.Component.year, Calendar.Component.month, Calendar.Component.day], from: date)
        let today = Calendar.current.dateComponents([Calendar.Component.era, Calendar.Component.year, Calendar.Component.month, Calendar.Component.day], from: Date())
        if components.year == today.year {
            //今年
            let df = DateFormatter()
            df.dateFormat = "MM/dd HH:mm"
            return df.string(from: date)
        } else {
            let df = DateFormatter()
            df.dateFormat = "yy/MM/dd HH:mm"
            return df.string(from: date)
        }
    }
}

